package com.syni.mdd.sjb.community.base.controller.protect;

import com.syni.mdd.sjb.common.component.utils.common.thread.ThreadPoolUtils;
import com.syni.mdd.sjb.common.component.utils.common.utils.AppConfig;
import com.syni.mdd.sjb.common.component.utils.common.utils.ResultMapHelper;
import com.syni.mdd.sjb.common.component.utils.redis.utils.RedisTemplateUtils;
import com.syni.mdd.sjb.community.base.config.QywxProperties;
import com.syni.mdd.sjb.community.base.constants.Constants;
import com.syni.mdd.sjb.community.base.entity.vo.rq.SetSessionInfoRqVo;
import com.syni.mdd.sjb.community.base.service.SjbQywxCompanyService;
import com.syni.mdd.sjb.community.base.utils.OAUtils;
import com.syni.mdd.sjb.community.base.utils.aes.WXBizMsgCrypt;
import lombok.extern.log4j.Log4j2;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.concurrent.TimeUnit;

@RestController
@Log4j2
@EnableConfigurationProperties(QywxProperties.class)
public class OAController {
    @Value("30")
    private int VALID_TIME; // token有效期()

    @Autowired
    SjbQywxCompanyService sjbQywxCompanyService;

    /**
     * 指令回调/其他回调接口
     *
     * @param request
     * @param response
     * @throws Exception
     */
    @RequestMapping(value = "/directCallback")
    public void directCallback(HttpServletRequest request, HttpServletResponse response) {
        log.info("----------------------------");
        log.info("this is directCallback");
        log.info("这是回调的请求参数:*********************################");
        for (String key : request.getParameterMap().keySet()) {
            log.info("这是回调的请求参数:{}", key);
            for (String value : request.getParameterMap().get(key)) {
                log.info("这是参数内容：{}", value);
            }
        }
        response.setCharacterEncoding("UTF-8");

        try {
            String corpid = request.getParameter("corpid");
            // 企业微信加密签名
            String msgSignature = request.getParameter("msg_signature");
            // 时间戳 与nonce结合使用，用于防止请求重放攻击
            String timestamp = request.getParameter("timestamp");
            // 校验时字符串
            String echostr = request.getParameter("echostr");
            // 随机数 与timestamp结合使用，用于防止请求重放攻击
            String nonce = request.getParameter("nonce");

            log.info("msgSignature: " + msgSignature);
            log.info("timestamp: " + timestamp);
            log.info("echostr: " + echostr);
            log.info("nonce: " + nonce);
            if ("GET".equals(request.getMethod())) { // get请求表示是验证
                log.info("corpid:" + corpid);
                String echostrDecrypt = null;
                // 校验服务商公司id
                WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(AppConfig.getProperty("sToken"), AppConfig.getProperty("sEncodingAESKey"),
                        AppConfig.getProperty("CorpID"));
                echostrDecrypt = wxcpt.VerifyURL(msgSignature, timestamp, nonce, echostr);
                log.info("verifyurl echostr: " + echostrDecrypt);
                response.setCharacterEncoding("UTF-8");
                response.getWriter().write(echostrDecrypt);
            } else { // post请求表示是真实数据
                // 获取传过来的xml信息（密文）
                InputStream ins = request.getInputStream();
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(ins));
                StringBuilder postData = new StringBuilder();
                String line = null;
                while ((line = bufferedReader.readLine()) != null) {
                    postData.append(line);
                }
                log.info("postData:" + postData);
                log.info("前置构造器参数：sToken:{}", AppConfig.getProperty("sToken"));
                log.info("前置构造器参数：sEncodingAESKey:{}", AppConfig.getProperty("sEncodingAESKey"));
                log.info("前置构造器参数：SuiteID:{}", AppConfig.getProperty("SuiteID"));
                WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(AppConfig.getProperty("sToken"), AppConfig.getProperty("sEncodingAESKey"),
                        AppConfig.getProperty("SuiteID"));
                String info = wxcpt.DecryptMsg(msgSignature, timestamp, nonce, postData.toString());
                System.out.println("解析的明文是：" + info); // 此处明文是xml信息

                // 解析xml，若InfoType是suite_ticket的话，说明是发送ticket的响应方式
                Document doc = DocumentHelper.parseText(info);
                Element root = doc.getRootElement();
                List<Element> elements = root.elements();
                elements.forEach(element -> log.info("这是成功回调后的参数xml内容输出,名称:{}，内容：{}", element.getName(),
                        element.getTextTrim()));
                String infoType = root.elementTextTrim("InfoType");
                String AuthCode = root.elementTextTrim("AuthCode");
                String state = root.elementTextTrim("state");
                log.info("当前请求的authCode : " + AuthCode);
                log.info("当前请求的state : " + state);
                log.info("当前请求类型为：{}", infoType);
                if ("suite_ticket".equals(infoType)) { // 此处只是进行suite_ticket的处理，若是需要其他的处理需要在这里添加类型
                    String suiteTicket = root.elementTextTrim("SuiteTicket");
                    log.info("拿到的ticket是: " + suiteTicket);
                    RedisTemplateUtils.getRedisTemplate().opsForValue().set(Constants.REDIS_KEY_TICKET + AppConfig.getProperty("SuiteID"),
                            suiteTicket, VALID_TIME, TimeUnit.MINUTES);
                } else if ("create_auth".equals(infoType)) {
                    RedisTemplateUtils.getRedisTemplate().opsForHash().put(Constants.REDIS_KEY_AUTH_CODE, AuthCode, AuthCode);
                    sjbQywxCompanyService.addAuthCode(AuthCode);
                } else if ("cancel_auth".equals(infoType)) {
                    String AuthCorpId = root.elementTextTrim("AuthCorpId");
                    ThreadPoolUtils.getExecutorService().submit(() -> {
                        sjbQywxCompanyService.cancelAuth(AuthCorpId);
                    });
                }
                response.getWriter().write("success");
            }
            log.info("----------------------------");
        } catch (Exception e) {
            //验证URL失败，错误原因请查看异常
            log.info(e.getMessage(), e);
        }
    }

    //设置授权配置
    @PostMapping("/setSessionInfo")
    public Object setSessionInfo(@RequestBody SetSessionInfoRqVo setSessionInfoRqVo) {
        boolean flag = OAUtils.setSessionInfo(setSessionInfoRqVo.getAuthType());
        if (flag) {
            return ResultMapHelper.success(null, "设置成功");
        } else {
            return ResultMapHelper.failure("设置失败");
        }
    }


    //测试
    @GetMapping("/redirect")
    public Object getUserInfo(String auth_code) {

        String providerToken = OAUtils.getProviderToken();
        System.out.println(providerToken);
        System.out.println(auth_code);
        return ResultMapHelper.success(providerToken);
    }
}
